#pragma once

#include <string>
#include <unordered_set>
#include <unordered_map>
#include <vector>
#include <memory>
#include <mutex>
#include <iostream>
#include <iomanip>
#include <sstream>
#include <algorithm>

namespace viml {

/**
 * 简化的字符串驻留池
 */
class SimpleStringInternPool {
public:
    // 字符串驻留统计信息
    struct SimplePoolStats {
        size_t total_interned_strings = 0;
        size_t total_interned_bytes = 0;
        size_t unique_strings = 0;
        size_t unique_bytes = 0;
        size_t total_accesses = 0;
        size_t cache_hits = 0;
        double hit_rate = 0.0;

        void clear() {
            total_interned_strings = 0;
            total_interned_bytes = 0;
            unique_strings = 0;
            unique_bytes = 0;
            total_accesses = 0;
            cache_hits = 0;
            hit_rate = 0.0;
        }
    };

private:
    // 字符串存储
    std::unordered_set<std::string> interned_strings_;
    std::unordered_map<std::string, size_t> access_counts_;

    // 配置参数
    static constexpr size_t MAX_POOL_SIZE = 5000;
    static constexpr size_t SHORT_STRING_THRESHOLD = 16;

    mutable std::mutex pool_mutex_;
    mutable SimplePoolStats stats_;

public:
    SimpleStringInternPool() {
        interned_strings_.reserve(1000);
        access_counts_.reserve(1000);
    }

    ~SimpleStringInternPool() {
        clear();
    }

    // 驻留字符串
    const std::string* intern(const std::string& str) {
        if (str.empty()) {
            return nullptr;
        }

        std::lock_guard<std::mutex> lock(pool_mutex_);

        // 检查是否已存在
        const std::string* existing = find(str);
        if (existing) {
            ++stats_.cache_hits;
            ++stats_.total_accesses;
            update_access_count(str);
            return existing;
        }

        // 添加新的驻留字符串
        auto insert_result = interned_strings_.insert(str);
        if (insert_result.second) {
            stats_.total_interned_strings++;
            stats_.total_interned_bytes += str.length();
            stats_.unique_strings++;
            stats_.unique_bytes += str.length();
        }

        update_access_count(str);
        ++stats_.total_accesses;

        return &(*insert_result.first);
    }

    // 查找字符串
    const std::string* find(const std::string& str) const {
        auto it = interned_strings_.find(str);
        return (it != interned_strings_.end()) ? &(*it) : nullptr;
    }

    bool contains(const std::string& str) const {
        return find(str) != nullptr;
    }

    SimplePoolStats get_stats() const {
        std::lock_guard<std::mutex> lock(pool_mutex_);

        auto result = stats_;

        // 计算命中率
        if (result.total_accesses > 0) {
            result.hit_rate = static_cast<double>(result.cache_hits) / result.total_accesses;
        }

        return result;
    }

    void reset_stats() {
        std::lock_guard<std::mutex> lock(pool_mutex_);
        stats_.clear();
    }

    void clear() {
        std::lock_guard<std::mutex> lock(pool_mutex_);

        interned_strings_.clear();
        access_counts_.clear();

        stats_.clear();
    }

    size_t size() const {
        std::lock_guard<std::mutex> lock(pool_mutex_);
        return interned_strings_.size();
    }

    void shrink_to_fit() {
        std::lock_guard<std::mutex> lock(pool_mutex_);

        if (interned_strings_.size() > MAX_POOL_SIZE) {
            // 简单的清理策略：移除访问频率最低的25%
            std::vector<std::pair<std::string, size_t>> entries;
            for (const auto& pair : access_counts_) {
                entries.emplace_back(pair.first, pair.second);
            }

            std::sort(entries.begin(), entries.end(),
                      [](const auto& a, const auto& b) { return a.second < b.second; });

            size_t to_remove = entries.size() / 4; // 保留75%，移除25%
            for (size_t i = 0; i < to_remove; ++i) {
                interned_strings_.erase(entries[i].first);
                access_counts_.erase(entries[i].first);
            }
        }
    }

    void print_stats() const {
        auto stats = get_stats();

        std::cout << "=== 简化字符串驻留池统计 ===" << std::endl;
        std::cout << "驻留字符串总数: " << stats.total_interned_strings << std::endl;
        std::cout << "驻留字节数: " << stats.total_interned_bytes << std::endl;
        std::cout << "唯一字符串数: " << stats.unique_strings << std::endl;
        std::cout << "唯一字节数: " << stats.unique_bytes << std::endl;
        std::cout << "总访问次数: " << stats.total_accesses << std::endl;
        std::cout << "缓存命中次数: " << stats.cache_hits << std::endl;
        std::cout << "缓存命中率: " << std::fixed << std::setprecision(2)
                  << (stats.hit_rate * 100) << "%" << std::endl;
        std::cout << "池大小: " << size() << std::endl;
        std::cout << "=================" << std::endl;
    }

    std::string generate_report() const {
        auto stats = get_stats();

        std::ostringstream report;
        report << "=== 简化字符串驻留池报告 ===" << std::endl;
        report << "驻留字符串总数: " << stats.total_interned_strings << std::endl;
        report << "唯一字符串数: " << stats.unique_strings << std::endl;
        report << "缓存命中率: " << std::fixed << std::setprecision(2)
               << (stats.hit_rate * 100) << "%" << std::endl;
        report << "平均字符串长度: " << std::fixed << std::setprecision(2)
               << (stats.unique_strings > 0 ? static_cast<double>(stats.unique_bytes) / stats.unique_strings : 0.0)
               << " 字节" << std::endl;
        report << "=================" << std::endl;

        return report.str();
    }

private:
    void update_access_count(const std::string& str) {
        auto it = access_counts_.find(str);
        if (it != access_counts_.end()) {
            it->second++;
        } else {
            access_counts_[str] = 1;
        }
    }
};

/**
 * 全局简化字符串驻留池
 */
class GlobalSimpleStringInternPool {
private:
    static std::unique_ptr<SimpleStringInternPool> instance_;
    static std::mutex instance_mutex_;
    static bool initialized_;

public:
    static SimpleStringInternPool& get_instance();
    static void initialize();
    static void shutdown();
    static bool is_initialized();
};

} // namespace viml